package org.example.mq.mqserver.core;

import org.example.mq.common.MqException;
import org.example.mq.mqserver.coreenum.ExchangeType;

public class Router {
    /*
    * 检查BindingKey是否合法
    * */
    public  boolean checkBindingKey(String bindingKey){
        if(bindingKey.length() == 0){
            return true;
        }
        for (int i = 0; i < bindingKey.length(); i++) {
            char ch = bindingKey.charAt(i);
            if(ch>='A'&& ch<='Z'){
                continue;
            }
            if(ch>='a'&& ch<='z'){
                continue;
            }
            if(ch>='0'&& ch<='9'){
                continue;
            }
            if(ch=='_'|| ch=='.'){
                continue;
            }
            if(ch=='*'|| ch=='#'){
                continue;
            }
            return false;
        }
        //检查格式是否合法（不合法aaa.bbb*.ccc|aaa.#b.ccc）
        String[] words = bindingKey.split("\\.");
        for (String word:words){
            if(word.length()>1&& (word.contains("*")||word.contains("#"))){
                return false;
            }
        }
//        判断通配符之间的相邻关系是否合法(下面的格式难实现，作用也不大)
        for (int i = 0; i < words.length - 1; i++) {
            if(words[i].equals("#") && words[i+1].equals("*")){
                return false;
            }
            if(words[i].equals("*") && words[i+1].equals("#")){
                return false;
            }
            if(words[i].equals("#") && words[i+1].equals("#")){
                return false;
            }
        }
        return true;
    }

    /*
    * 检查routingKey是否合法
    * */
    public  boolean checkRoutingKey(String routingKey){
        if(routingKey.length()==0){
            return true;
        }
        for (int i = 0; i < routingKey.length(); i++) {
            char ch = routingKey.charAt(i);
            if(ch>='A'&& ch<='Z'){
                continue;
            }
            if(ch>='a'&& ch<='z'){
                continue;
            }
            if(ch>='0'&& ch<='9'){
                continue;
            }
            if(ch=='_'|| ch=='.'){
                continue;
            }
            if(ch=='*'|| ch=='#'){
                continue;
            }
            return false;
        }
        return true;
    }


    /*
    * 判断交换机类型和消息的匹配（转发规则的设定）
    * */
    public boolean route(ExchangeType type, Binding binding, Message message) throws MqException {
        if(type == ExchangeType.FANOUT){
            return true;
        }else if (type==ExchangeType.TOPIC) {
            return routeTopic(binding,message);
        }else {
            throw new MqException("交换机类型异常");
        }
    }

    private boolean routeTopic(Binding binding, Message message) {
        String[] bindingTokens = binding.getBindingKey().split("\\.");
        String[] routingTokens = message.getRoutingKey().split("\\.");

        int bindingIndex = 0;
        int routingIndex = 0;
        while(bindingIndex<bindingTokens.length && routingIndex<routingTokens.length){
//            情况1：binding为 * 对应routing 匹配任意一个都可以(直接抬走下一个)
            if(bindingTokens[bindingIndex].equals("*")){
                bindingIndex++;
                routingIndex++;
                continue;
//            情况2：binding为 #
            }else if(bindingTokens[bindingIndex].equals("#")){
//                1.# 号 后面没有内容
                bindingIndex++;
                if(bindingIndex==bindingTokens.length){
                    return true;
                }
//                2.# 号 后面有内容，在routingKey后面一直找，找到和bindingKey对应的内容（如果存在，则正常进行下一个部分的判断，不存在直接报错）
                //如果找到，返回对应的下表，如果没有找到返回-1
                routingIndex = findNextMatch(routingTokens,routingIndex,bindingTokens[bindingIndex]);
                if(routingIndex==-1){
                    return false;
                }
                //如果找到，将返回的下标进行+1，进行下一位的正常判断
                bindingIndex++;
                routingIndex++;
            }else {
//             情况3：普通的字符串，进行正常的判断即可
                if(!bindingTokens[bindingIndex].equals(routingTokens[routingIndex])){
                    return false;
                }
                bindingIndex++;
                routingIndex++;
            }
        }
//        情况4：有一方走完了，导致跳出循环，这种情况不能返回true，需要在加一步判断，是不是双方都走完了
        if(bindingIndex == bindingTokens.length && routingIndex == routingTokens.length){
            return true;
        }
        return false;
    }

    private int findNextMatch(String[] routingTokens, int routingIndex, String bindingToken) {
        for (int i = routingIndex; i < routingTokens.length; i++) {
            String n = routingTokens[i];
            if(n.equals(bindingToken)){
                //注意：这里返回i，返回routingKey的数值一直没有变化
                return i;
            }
        }
        return -1;

    }
}
